package seguranca.manager;

import geral.manager.UtilManager;
import geral.util.FacesUtil;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import aspecto.annotation.Permissao;
import br.com.sgc.entities.geral.PacienteAnimal;
import br.com.sgc.entities.geral.PacientePessoa;
import br.com.sgc.entities.medico.Medico;
import br.com.sgc.entities.rh.Funcionario;
import br.com.sgc.entities.seguranca.Perfil;
import br.com.sgc.entities.seguranca.Usuario;
import br.com.sgc.exception.ValidacaoException;
import br.com.sgc.permissao.Role;
import br.com.sgc.session.MedicoSession;
import br.com.sgc.session.SegurancaSession;

@Named
@SessionScoped
public class SegurancaManager implements Serializable{

	private static final long serialVersionUID = -961414153500300194L;

	@EJB private SegurancaSession segurancaSession;
	@EJB private MedicoSession medicoSession;
	
	private List<Usuario> listUsuario = new ArrayList<Usuario>();
	private List<String> listPermissao;
	private Usuario usuario = new Usuario();
	private Usuario usuarioLogado = null;
	private Funcionario funcionarioLogado = null;

	private Funcionario funcionario = new Funcionario();
	private List<Funcionario> listFuncionario = new ArrayList<Funcionario>();
	
	private List<Medico> medicos = new ArrayList<Medico>();

	private String modulo;
	
	private Boolean showVisualizacaoMedico = false;
	
	private Integer maxTime;
	
	private Integer minTime;
	
	private Integer maxDate;
	
	private Integer minDate;
	
	private String template;
	
	private String paginaHome;
	
	private String retorno;

	@Inject
	private UtilManager utilManager;

	public String login() {
		try {
			usuarioLogado = segurancaSession.loginUsuario(usuario);
			primeiroAcesso();
			if(retorno == null){
				novoAcesso();
			}
		} catch (ValidacaoException e) {
			FacesUtil.mensInfo(e.getMessage());
			return null;
		}
		return retorno;
	}
	
	private void novoAcesso() {
		if(!usuarioLogado.isSuperUsuario())
			listPermissao = Arrays.asList(usuarioLogado.getPerfilUsuario().getPermissoesArray());
		
		validateVisualizacaoMedico();
		iniciarAccesso();
		generateTemplate();
		retorno = "homeSGC";
	}

	private void generateTemplate() {
		if(getIsClinica()){
			utilManager.getAgendaManager().setPaciente(new PacientePessoa());
			template = "/template/templateClinica.xhtml";
			paginaHome = "/medico/homeClinica.xhtml";
		} else if(getIsVeterinaria()){
			utilManager.getAgendaManager().setPaciente(new PacienteAnimal());
			template = "/template/templateVeterinaria.xhtml";
			paginaHome = "/veterinaria/homeVeterinaria.xhtml";
		}
	}

	private void validateVisualizacaoMedico() {
		funcionarioLogado = utilManager.getFuncionarioManager().getFuncionarioSession().findByUsuario(usuarioLogado);
		try {
			utilManager.getMedicoManager().setMedico(utilManager.getMedicoManager().getMedicoSession().findById(Medico.class, funcionarioLogado.getId()));
			utilManager.getMedicoManager().showVisualizacaoMedico();
			showVisualizacaoMedico = true;
		} catch (Exception e) {
			showVisualizacaoMedico = false;
		}
	}

	private void iniciarAccesso() {
		medicos = medicoSession.findAll(Medico.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId());
		minTime = Integer.parseInt(usuarioLogado.getClinica().getHorarioAbertura().substring(0,2));
		maxTime = Integer.parseInt(usuarioLogado.getClinica().getHorarioFechamento().substring(0,2));
		Calendar cal = Calendar.getInstance();
		minDate = cal.get(Calendar.YEAR);
		cal.add(Calendar.YEAR, 10);
		maxDate = cal.get(Calendar.YEAR);
		
		
	}

	private void primeiroAcesso() {
		if(usuarioLogado.getClinica() == null || usuarioLogado.getClinica().getId() == null){
			retorno = "primeiroAcesso";
		}
	}

	public String logout(){
		usuarioLogado = null;
		HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
		if(session != null){
			session.invalidate();
		}
		generateTemplate();
		return "/login.xhtml";
		
	}

	public String showSistemaUsuario() {
		return "homeSeguranca";
	}

	@Permissao(role = Role.Sistema_Usuarios_Seguranca_Salvar)
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public String prepareSave() {
		funcionario = new Funcionario();
		listFuncionario = new ArrayList<Funcionario>();
		utilManager.getPerfilManager().list();
		usuario = new Usuario();
		return "formUsuario";
	}

	@Permissao(role = Role.Sistema_Usuarios_Seguranca_Atualizar)
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public String prepareUpdate() {
		utilManager.getPerfilManager().list();
		usuario = segurancaSession.findById(Usuario.class, usuario.getId(),true);
		if(usuario.getPerfilUsuario() == null){
			usuario.setPerfilUsuario(new Perfil());
		}
		usuario.setSenha(null);
		return "formUsuario";
	}

	@Permissao(role = Role.Sistema_Usuarios_Seguranca_Atualizar)
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public String update() {
		try {
			segurancaSession.update(usuario, false);
			usuario = new Usuario();
			return list();
			
		// Erros de negócio
		} catch (ValidacaoException e) {
			e.printStackTrace();
			FacesUtil.mensWarn(e.getMessage());
		}

		return null;
	}

	public String list() {
		listUsuario = segurancaSession.findAll(Usuario.class, utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getId(), true);
		return "listUsuario";
	}
	
	public void findFuncionario(AjaxBehaviorEvent event){
		listFuncionario.clear();
		listFuncionario = utilManager.getFuncionarioManager().getFuncionarioSession().searchFuncionarioSemUsuario(funcionario);
	}
	
	// ======================== METODO AUXILIAR PARA RECUPERAR IP ======= //
	public String getRemoteIp() {
		String remoteAddr = "";
		Object request = FacesContext.getCurrentInstance().getExternalContext().getRequest();
		if (request instanceof HttpServletRequest) {
			HttpServletRequest req = (HttpServletRequest) request;
			remoteAddr = req.getHeader("X-FORWARDED-FOR");
			if(remoteAddr == null){
				remoteAddr = req.getRemoteAddr();
			}
		}
		return remoteAddr;
	}
	
	public void validateLogin(AjaxBehaviorEvent event){
		try {
			segurancaSession.validateLogin(usuario);
		} catch (ValidacaoException e) {
			FacesUtil.mensWarn(e.getMessage());
		}
	}
	
	public boolean getIsVeterinaria(){
		return usuarioLogado != null && usuarioLogado.getClinica()!= null && usuarioLogado.getClinica().getTipoClinica().isVeterinaria();
	}
	
	public boolean getIsClinica(){
		return usuarioLogado != null && usuarioLogado.getClinica()!= null && usuarioLogado.getClinica().getTipoClinica().isClinica();
	}
	
	// ========================= GET'S AND SET'S ========================= //

	public Usuario getUsuario() {
		return usuario;
	}

	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

	public Usuario getUsuarioLogado() {
		return usuarioLogado;
	}

	public void setUsuarioLogado(Usuario usuarioLogado) {
		this.usuarioLogado = usuarioLogado;
	}

	public List<Usuario> getListUsuario() {
		return listUsuario;
	}

	public void setListUsuario(List<Usuario> listUsuario) {
		this.listUsuario = listUsuario;
	}

	public Funcionario getFuncionario() {
		return funcionario;
	}

	public void setFuncionario(Funcionario funcionario) {
		this.funcionario = funcionario;
	}

	public List<Funcionario> getListFuncionario() {
		return listFuncionario;
	}

	public void setListFuncionario(List<Funcionario> listFuncionario) {
		this.listFuncionario = listFuncionario;
	}

	public SegurancaSession getSegurancaSession() {
		return segurancaSession;
	}

	public void setSegurancaSession(SegurancaSession segurancaSession) {
		this.segurancaSession = segurancaSession;
	}

	public String getModulo() {
		return modulo;
	}

	public void setModulo(String modulo) {
		this.modulo = modulo;
	}

	public List<Medico> getMedicos() {
		return medicos;
	}

	public void setMedicos(List<Medico> medicos) {
		this.medicos = medicos;
	}

	public Boolean getShowVisualizacaoMedico() {
		return showVisualizacaoMedico;
	}

	public void setShowVisualizacaoMedico(Boolean showVisualizacaoMedico) {
		this.showVisualizacaoMedico = showVisualizacaoMedico;
	}

	public List<String> getListPermissao() {
		return listPermissao;
	}

	public void setListPermissao(List<String> listPermissao) {
		this.listPermissao = listPermissao;
	}

	public Funcionario getFuncionarioLogado() {
		return funcionarioLogado;
	}

	public void setFuncionarioLogado(Funcionario funcionarioLogado) {
		this.funcionarioLogado = funcionarioLogado;
	}

	public Integer getMaxTime() {
		return maxTime;
	}

	public void setMaxTime(Integer maxTime) {
		this.maxTime = maxTime;
	}

	public Integer getMinTime() {
		return minTime;
	}

	public void setMinTime(Integer minTime) {
		this.minTime = minTime;
	}

	public String getTemplate() {
		return template;
	}

	public void setTemplate(String template) {
		this.template = template;
	}

	public String getPaginaHome() {
		return paginaHome;
	}

	public void setPaginaHome(String paginaHome) {
		this.paginaHome = paginaHome;
	}

	public Integer getMaxDate() {
		return maxDate;
	}

	public void setMaxDate(Integer maxDate) {
		this.maxDate = maxDate;
	}

	public Integer getMinDate() {
		return minDate;
	}

	public void setMinDate(Integer minDate) {
		this.minDate = minDate;
	}
}